package sg.edu.nus.iss.billing.controller;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import sg.edu.nus.iss.billing.exceptions.ControllerException;
import sg.edu.nus.iss.billing.model.calculation.*;
import sg.edu.nus.iss.billing.model.charge.*;
import sg.edu.nus.iss.billing.model.subscription.ISubscribable;

/**
 * @author ZiFeng, Thurein, YinNi
 *  To handle populating the charges relating to service.
 */
public class ChargeController {

	public enum ChargeMethods {
		PerMonth, PerTransaction, PerDay
	}

	public enum Charges {
		AdditionalChSubscriptionCharge, CableTVSubscriptionCharge, DigitalCallTransferSubscriptionCharge, DigitalIDDUsageCharge, DigitalLineSubscriptionCharge, DigitalLocalUsageCharge, MobileDataServiceSubscriptionCharge, MobileLineSubscriptionCharge, MobileLocalUsageCharge, mobileRoamingSubscriptionCharge, mobileRoamingUsageCharge, MobileIDDUsageCharge
	}

	public enum ChargeTypes {
		SubscriptionFee, UsageFee
	}

	public enum RateTypes {
		CableTVSubscriptionChargeRate, AdditionalChSubscriptionChargeRate, DigitalCallTransferSubscriptionChargeRate, DigitalIDDUsageChargeRate, DigitalLineSubscriptionChargeRate, DigitalLocalUsageChargeRate, MobileDataServiceSubscriptionChargeRate, MobileLineSubscriptionChargeRate, MobileIDDUsageChargeRate, MobileLocalUsageChargeRate, mobileRoamingSubscriptionChargeRate, mobileRoamingUsageChargeRate
	}

	private static String dataLocation = "data/inbound/Charges/";

	public static List<IChargable> getServiceCharges(ISubscribable service) throws ControllerException {

		try {
			return readChargesFromFile(service);

		} catch (Exception e) {
			e.printStackTrace();
			throw new ControllerException("Exception while fetching the charges for the service "
					+ service.getServiceId());
		}

	}

	protected static IChargable createCharge(ChargeTypes type, ISubscribable chargingService, String description) {
		IChargable charge = null;
		if (type.equals(ChargeTypes.SubscriptionFee))
			charge = new SubscriptionFee(chargingService, description);
		else if (type.equals(ChargeTypes.UsageFee))
			charge = new UsageFee(chargingService, description);
		return charge;
	}

	protected static IChargeMethod createChargeMethod(ChargeMethods methodType) {
		IChargeMethod chargeMethod = null;
		if (methodType.equals(ChargeMethods.PerMonth))
			chargeMethod = new PerMonth();
		else if (methodType.equals(ChargeMethods.PerTransaction))
			chargeMethod = new PerTransaction();
		else if (methodType.equals(ChargeMethods.PerDay))
			chargeMethod = new PerDay();
		return chargeMethod;
	}

	protected static List<IChargable> readChargesFromFile(ISubscribable service) throws Exception {
		List<IChargable> charges = new ArrayList<IChargable>();
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(dataLocation
				+ service.getServiceId() + ".txt")));

		String line = null;
		while ((line = bufferedReader.readLine()) != null) {
			String[] strs = line.split(",");
			if (strs != null && strs.length == 4) {
				IChargable charge = createCharge(ChargeTypes.valueOf(strs[2]), service, strs[0]);
				charge.setRate(getRate(RateTypes.valueOf(strs[1])));
				charge.setChargeMethod(createChargeMethod(ChargeMethods.valueOf(strs[3])));
				charge.setDescription(strs[0]);
				charges.add(charge);
			}
		}
		bufferedReader.close();
		return charges;

	}

	private static Rate getRate(RateTypes type) {
		return RateController.getInstance().getRate(type.toString());
	}

}
